---
title: "Listbox"
description: "A listbox displays a list of options and allows a user to select one or more of them."
---

import {listboxContent} from "@/content/components/listbox";

# Listbox

A listbox displays a list of options and allows a user to select one or more of them.

<ComponentLinks component="listbox" reactAriaHook="useListBox" />

---

<CarbonAd/>

## Installation

<PackageManagers
  showGlobalInstallWarning
  commands={{
    cli: "npx heroui-cli@latest add listbox",
    npm: "npm install @heroui/listbox",
    yarn: "yarn add @heroui/listbox",
    pnpm: "pnpm add @heroui/listbox",
    bun: "bun add @heroui/listbox"
  }}
/>

## Import

HeroUI exports 3 listbox-related components:

- **Listbox**: The main component, which is a wrapper for the other components.
- **ListboxSection**: The component that contains a group of listbox items.
- **ListboxItem**: The component that represents a listbox item.

<ImportTabs
  commands={{
    main: `import {
    Listbox,
    ListboxSection,
    ListboxItem
} from "@heroui/react";`,
    individual: `import {
    Listbox,
    ListboxSection,
    ListboxItem
} from "@heroui/listbox";`,
  }}
/>

## Usage

<CodeDemo title="Usage" files={listboxContent.usage} />

### Dynamic items

Listbox follows the [Collection Components API](https://react-spectrum.adobe.com/react-stately/collections.html), accepting both static and dynamic collections.

- **Static**: The usage example above shows the static implementation, which can be used when the full list of options is known ahead of time.
- **Dynamic**: The example below can be used when the options come from an external data source such as an API call, or update over time.

<CodeDemo title="Dynamic items" files={listboxContent.dynamic} />

### Disabled Keys

Listbox items can be disabled using the `disabledKeys` prop to the `Listbox` component.

<CodeDemo title="Disabled Keys" files={listboxContent.disabledKeys} />

> **Note**: It's important to have a unique key for each item, otherwise the disabled keys will not work.

### Variants

You can use the `variant` in the `Listbox` component to change the `hover` style of the listbox items.

<CodeDemo title="Variants" files={listboxContent.variants} />

### Single Selection

You can set the `selectionMode` property as `single` to allow the user to select only one item at a time.

<CodeDemo
  title="Single Selection"
  files={listboxContent.singleSelection}
/>

### Multiple Selection

You can set the `selectionMode` property as `multiple` to allow the user to select multiple items at a time.

<CodeDemo
  title="Multiple Selection"
  files={listboxContent.multipleSelection}
/>

> **Note**: To allow empty selection, you can set the `disallowEmptySelection` property as `false`.

### With Icons

It is possible to add icons to the listbox items using the `startContent` / `endContent` props.

<CodeDemo title="With Icons" files={listboxContent.icons} />

> **Note**: If you use `currentColor` as the icon color, the icon will have the same color as the item text.

### With Description

You can use the `description` prop to add a description to the listbox item.

<CodeDemo
  title="With Description"
  files={listboxContent.description}
/>

### With Top & Bottom Content

You can use the `topContent` and `bottomContent` props to add content above and below the listbox items.

<CodeDemo title="With Top & Bottom Content" files={listboxContent.topContent} />

### With Sections

You can use the `ListboxSection` component to group listbox items.

<CodeDemo title="With Sections" files={listboxContent.sections} />

> **Note**: Sections without a `title` must provide an `aria-label` for accessibility.

### Routing

The `<ListboxItem>` component works with frameworks and client side routers like [Next.js](https://nextjs.org/) and
[React Router](https://reactrouter.com/en/main). See the [Routing](/docs/guide/routing) guide to learn how to set this up.

```jsx
import {Listbox, ListboxItem} from "@heroui/react";

function App() {
  return (
    <Listbox>
      <ListboxItem key="home" href="/home">
        Home
      </ListboxItem>
      <ListboxItem key="about" href="/about">
        About
      </ListboxItem>
    </Listbox>
  );
}
```

### Virtualization

Listbox supports virtualization, which allows efficient rendering of large lists by only rendering items that are visible in the viewport. You can enable virtualization by setting the `isVirtualized` prop to `true`.

<CodeDemo
  title="Virtualization"
  files={listboxContent.virtualization}
/>

> **Note**: The virtualization strategy is based on the [@tanstack/react-virtual](https://tanstack.com/virtual/latest) package, which provides efficient rendering of large lists by only rendering items that are visible in the viewport.
#### Ten Thousand Items

Here's an example of using virtualization with 10,000 items.

<CodeDemo title="Ten Thousand Items" files={listboxContent.virtualizationTenThousand} />

## Slots

Listbox has 3 components with slots the base one `Listbox`, `ListboxItem` and `ListboxSection` components.

### Listbox

- **base**: The main wrapper for the listbox component. This slot wraps the `topContent`, `bottomContent` and the `list` slot.
- **list**: The slot for the listbox component. You can see this slot as the `ul` slot.
- **emptyContent**: The slot content to display when the collection is empty.

### ListboxItem

- **base**: The main slot for the listbox item. It wraps all the other slots.
- **wrapper**: The `title` and `description` wrapper.
- **title**: The title of the listbox item.
- **description**: The description of the listbox item.
- **selectedIcon**: The selected icon slot. This is only visible when the item is selected.

### ListboxSection

- **base**: The main slot for the listbox section. It wraps all the other slots.
- **heading**: The title that is render on top of the section group.
- **group**: The group of listbox items.
- **divider**: The divider that is render between the groups. This is only visible when `showDivider` is `true`.

### Customizing the listbox

You can customize the `Listbox` items style by using the `itemClasses` prop and passing custom Tailwind CSS classes.

<CodeDemo title="Custom Styles" files={listboxContent.customStyles} />

> **Note**: In the above example, we've utilized the [Boxicons](https://boxicons.com/) icons collection.

<Spacer y={4} />

### Keyboard Interactions

| Key                                  | Description                                                                                                      |
| ------------------------------------ | ---------------------------------------------------------------------------------------------------------------- |
| <Kbd>Home</Kbd>                      | Moves focus to the first item.                                                                                   |
| <Kbd>End</Kbd>                       | Moves focus to the last item.                                                                                    |
| <Kbd>ArrowDown</Kbd>                 | When focus is on an item, moves focus to the next item.                                                          |
| <Kbd>ArrowUp</Kbd>                   | When focus is on an item, moves focus to the previous item.                                                      |
| <Kbd>Enter</Kbd> or <Kbd>Space</Kbd> | When focus is on an item, selects the item.                                                                      |
| <Kbd>A-Z</Kbd> or <Kbd>a-z</Kbd>     | Moves focus to the next menu item with a label that starts with the typed character if such an menu item exists. |

## Data Attributes

`ListboxItem` has the following attributes on the `base` element:

- **data-disabled**:
  When the listbox item is disabled. Based on listbox `disabledKeys` prop.
- **data-selected**:
  When the listbox item is selected. Based on listbox `selectedKeys` prop.
- **data-selectable**:
  When the listbox item is selectable. Based on listbox `selectionMode` prop.
- **data-hover**:
  When the listbox item is being hovered. Based on [useHover](https://react-spectrum.adobe.com/react-aria/useHover.html)
- **data-pressed**:
  When the listbox item is pressed. Based on [usePress](https://react-spectrum.adobe.com/react-aria/usePress.html)
- **data-focus**:
  When the listbox item is being focused. Based on [useFocusRing](https://react-spectrum.adobe.com/react-aria/useFocusRing.html).
- **data-focus-visible**:
  When the listbox item is being focused with the keyboard. Based on [useFocusRing](https://react-spectrum.adobe.com/react-aria/useFocusRing.html).

<Spacer y={4} />

## Accessibility

- Exposed to assistive technology as a `listbox` using ARIA.
- Support for single, multiple, or no selection.
- Support for disabled items.
- Support for sections.
- Labeling support for accessibility.
- Support for mouse, touch, and keyboard interactions.
- Tab stop focus management.
- Keyboard navigation support including arrow keys, home/end, page up/down, select all, and clear.
- Automatic scrolling support during keyboard navigation.
- Typeahead to allow focusing options by typing text.

<Spacer y={4} />

## API

### Listbox Props

<APITable
  data={[
    {
      attribute: "children*",
      type: "ReactNode[]",
      description: "The children to render. Usually a list of ListboxItem or ListboxSection",
      default: "-"
    },
    {
      attribute: "items",
      type: "Iterable<T>",
      description: "Item objects in the collection. (dynamic)",
      default: "-"
    },
    {
      attribute: "variant",
      type: "solid | bordered | light | flat | faded | shadow",
      description: "The listbox items appearance style.",
      default: "solid"
    },
    {
      attribute: "color",
      type: "default | primary | secondary | success | warning | danger",
      description: "The listbox items color theme.",
      default: "default"
    },
    {
      attribute: "selectionMode",
      type: "none | single | multiple",
      description: "The type of selection that is allowed in the collection.",
      default: "-"
    },
    {
      attribute: "selectedKeys",
      type: "React.Key[]",
      description: "The currently selected keys in the collection (controlled).",
      default: "-"
    },
    {
      attribute: "disabledKeys",
      type: "React.Key[]",
      description: "The item keys that are disabled. These items cannot be selected, focused, or otherwise interacted with.",
      default: "-"
    },
    {
      attribute: "defaultSelectedKeys",
      type: "all | React.Key[]",
      description: "The initial selected keys in the collection (uncontrolled).",
      default: "-"
    },
    {
      attribute: "disallowEmptySelection",
      type: "boolean",
      description: "Whether the collection allows empty selection.",
      default: "false"
    },
    {
      attribute: "shouldHighlightOnFocus",
      type: "boolean",
      description: "Whether the focused item should be highlighted. It applies the same styles to the items as when hovered.",
      default: "false"
    },
    {
      attribute: "autoFocus",
      type: "boolean | first | last",
      description: "Where the focus should be set.",
      default: "false"
    },
    {
      attribute: "topContent",
      type: "ReactNode",
      description: "The content to display above the listbox items.",
      default: "-"
    },
    {
      attribute: "bottomContent",
      type: "ReactNode",
      description: "The content to display below the listbox items.",
      default: "-"
    },
    {
      attribute: "emptyContent",
      type: "ReactNode",
      description: "The content to display when the collection is empty.",
      default: "No items."
    },
    {
      attribute: "shouldFocusWrap",
      type: "boolean",
      description: "Whether keyboard navigation is circular.",
      default: "false"
    },   
    {
      attribute: "isVirtualized",
      type: "boolean",
      description: "Whether to enable virtualization.",
      default: "false"
    },
    {
      attribute: "virtualization",
      type: "Record<\"maxListboxHeight\" & \"itemHeight\", number>",
      description: "Configuration for virtualization, optimizing rendering for large datasets. Required if isVirtualized is set to true.",
      default: "-",
    },
    {
      attribute: "hideEmptyContent",
      type: "boolean",
      description: "Whether to not display the empty content when the collection is empty.",
      default: "false"
    },
    {
      attribute: "hideSelectedIcon",
      type: "boolean",
      description: "Whether to hide the check icon when the items are selected.",
      default: "false"
    },
    {
      attribute: "disableAnimation",
      type: "boolean",
      description: "Whether to disable the animation of the listbox items.",
      default: "false"
    },
    {
      attribute: "selectionBehavior",
      type: "'toggle' | 'replace'",
      description: "How multiple selection should behave in the collection.",
      default: "toggle"
    },
    {
      attribute: "classNames",
      type: "Partial<Record<\"base\" | \"list\" | \"emptyContent\", string>>",
      description: "Allows to set custom class names for the listbox slots.",
      default: "-"
    },
    {
      attribute: "itemClasses",
      type: "Partial<Record<\"base\" | \"wrapper\" | \"title\" | \"description\" | \"selectedIcon\", string>>",
      description: "Allows to set custom class names for the listbox item slots.",
      default: "-"
    }
  ]}
/>

### Listbox Events

<APITable
  data={[
    {
      attribute: "onAction",
      type: "(key: React.Key) => void",
      description: "Handler that is called when a user performs an action on an item. The exact user event depends on the collection's selectionBehavior prop and the interaction modality.",
      default: "-"
    },
    {
      attribute: "onSelectionChange",
      type: "(keys: React.Key[]) => void",
      description: "Handler that is called when the selection changes.",
      default: "-"
    }
  ]}
/>

### ListboxSection Props

<APITable
  data={[
    {
      attribute: "children*",
      type: "ReactNode",
      description: "The contents of the listbox section. Usually a list of ListboxItem components. (static)",
      default: "-"
    },
    {
      attribute: "title",
      type: "string",
      description: "The title of the listbox section.",
      default: "-"
    },
    {
      attribute: "items",
      type: "Iterable<T>",
      description: "Item objects in the collection. (dynamic)",
      default: "-"
    },
    {
      attribute: "hideSelectedIcon",
      type: "boolean",
      description: "Whether to hide the check icon when the items are selected.",
      default: "false"
    },
    {
      attribute: "showDivider",
      type: "boolean",
      description: "Whether to show the divider between the groups.",
      default: "false"
    },
    {
      attribute: "dividerProps",
      type: "DividerProps",
      description: "The divider component props.",
      default: "-"
    },
    {
      attribute: "classNames",
      type: "Partial<Record<\"base\" | \"heading\" | \"group\" | \"divider\", string>>",
      description: "Allows to set custom class names for the listbox section slots.",
      default: "-"
    },
    {
      attribute: "itemClasses",
      type: "Partial<Record<\"base\" | \"wrapper\" | \"title\" | \"description\" | \"shortcut\" | \"selectedIcon\", string>>",
      description: "Allows to set custom class names for the listbox item slots.",
      default: "-"
    }
  ]}
/>

### ListboxItem Props

<APITable
  data={[
    {
      attribute: "children*",
      type: "ReactNode",
      description: "The contents of the listbox item.",
      default: "-"
    },
    {
      attribute: "key",
      type: "React.Key",
      description: "The unique key for the listbox item.",
      default: "-"
    },
    {
      attribute: "title",
      type: "string | ReactNode",
      description: "The title of the listbox item.",
      default: "-"
    },
    {
      attribute: "textValue",
      type: "string",
      description: "A string representation of the item's contents, used for features like typeahead.",
      default: "-"
    },
    {
      attribute: "description",
      type: "string | ReactNode",
      description: "The description of the listbox item.",
      default: "-"
    },
    {
      attribute: "shortcut",
      type: "string | ReactNode",
      description: "The listbox item keyboard shortcut.",
      default: "-"
    },
    {
      attribute: "startContent",
      type: "ReactNode",
      description: "The start content of the listbox item.",
      default: "-"
    },
    {
      attribute: "endContent",
      type: "ReactNode",
      description: "The end content of the listbox item. This is positioned after the shortcut and the selected icon.",
      default: "-"
    },
    {
      attribute: "selectedIcon",
      type: "ListboxItemSelectedIconProps",
      description: "Custom icon to render when the item is selected.",
      default: "-"
    },
    {
      attribute: "href",
      type: "string",
      description: "A URL to link to. See MDN.",
      default: "-"
    },
    {
      attribute: "target",
      type: "HTMLAttributeAnchorTarget",
      description: "The target window for the link. See MDN.",
      default: "-"
    },
    {
      attribute: "rel",
      type: "string",
      description: "The relationship between the linked resource and the current page. See MDN.",
      default: "-"
    },
    {
      attribute: "download",
      type: "boolean | string",
      description: "Causes the browser to download the linked URL. A string may be provided to suggest a file name. See MDN.",
      default: "-"
    },
    {
      attribute: "ping",
      type: "string",
      description: "A space-separated list of URLs to ping when the link is followed. See MDN.",
      default: "-"
    },
    {
      attribute: "referrerPolicy",
      type: "HTMLAttributeReferrerPolicy",
      description: "How much of the referrer to send when following the link. See MDN.",
      default: "-"
    },
    {
      attribute: "shouldHighlightOnFocus",
      type: "boolean",
      description: "Whether the focused item should be highlighted. It applies the same styles to the item as when hovered.",
      default: "false"
    },
    {
      attribute: "hideSelectedIcon",
      type: "boolean",
      description: "Whether to hide the check icon when the item is selected.",
      default: "false"
    },
    {
      attribute: "showDivider",
      type: "boolean",
      description: "Whether to show a divider below the item.",
      default: "false"
    },
    {
      attribute: "isDisabled",
      type: "boolean",
      description: "Whether the listbox item should be disabled. (Deprecated) pass disabledKeys to Listbox instead.",
      default: "false"
    },
    {
      attribute: "isSelected",
      type: "boolean",
      description: "Whether the listbox item should be selected. (Deprecated) pass selectedKeys to Listbox instead.",
      default: "false"
    },
    {
      attribute: "isReadOnly",
      type: "boolean",
      description: "Whether the listbox item press events should be ignored.",
      default: "false"
    },
    {
      attribute: "classNames",
      type: "Partial<Record<\"base\" | \"wrapper\" | \"title\" | \"description\" | \"shortcut\" | \"selectedIcon\", string>>",
      description: "Allows to set custom class names for the listbox item slots.",
      default: "-"
    }
  ]}
/>

### ListboxItem Events

<APITable
  data={[
    {
      attribute: "onAction",
      type: "() => void",
      description: "Handler that is called when the listbox item is selected. (Deprecated) pass to Listbox instead.",
      default: "-"
    },
    {
      attribute: "onPress",
      type: "(e: PressEvent) => void",
      description: "Handler called when the press is released over the target.",
      default: "-"
    },
    {
      attribute: "onPressStart",
      type: "(e: PressEvent) => void",
      description: "Handler called when a press interaction starts.",
      default: "-"
    },
    {
      attribute: "onPressEnd",
      type: "(e: PressEvent) => void",
      description: "Handler called when a press interaction ends, either over the target or when the pointer leaves the target.",
      default: "-"
    },
    {
      attribute: "onPressChange",
      type: "(isPressed: boolean) => void",
      description: "Handler called when the press state changes.",
      default: "-"
    },
    {
      attribute: "onPressUp",
      type: "(e: PressEvent) => void",
      description: "Handler called when a press is released over the target, regardless of whether it started on the target or not.",
      default: "-"
    },
    {
      attribute: "onKeyDown",
      type: "(e: KeyboardEvent) => void",
      description: "Handler called when a key is pressed.",
      default: "-"
    },
    {
      attribute: "onKeyUp",
      type: "(e: KeyboardEvent) => void",
      description: "Handler called when a key is released.",
      default: "-"
    },
    {
      attribute: "onClick",
      deprecated: true,
      type: "MouseEventHandler",
      description: "The native button click event handler (Deprecated) use onPress instead.",
      default: "-"
    }
  ]}
/>

---

### Types

#### Listbox Item Selected Icon Props

```ts
export type ListboxItemSelectedIconProps = {
  /**
   * The current icon, usually an checkmark icon.
   */
  icon?: ReactNode;
  /**
   * The current selected status.
   */
  isSelected?: boolean;
  /**
   * The current disabled status.
   * @default false
   */
  isDisabled?: boolean;
};

type selectedIcon?: ReactNode | ((props: ListboxItemSelectedIconProps) => ReactNode) | null;
```
